home *** CD-ROM | disk | FTP | other *** search
- /***************************************************
- * *
- * chkfrag - check disk for fragmentation *
- * *
- ***************************************************/
-
- #include <stdio.h> /* standard library */
- #include <dos.h> /* dos access and registers */
- #include <malloc.h> /* memory allocation */
- #include <stdlib.h> /* common lib modules */
-
- #define UINT unsigned int /* unsigned integer type */
- #define ULONG unsigned long /* unsigned long type */
- #define NOT ! /* logical not */
- #define BOOT b_rec /* boot record shorthand */
- #define FILES (_A_SYSTEM | _A_HIDDEN | _A_SUBDIR) /* files type */
- #define LABEL (_A_VOLID) /* label type */
- #define CLEAR(s,c) strclr(s,c,sizeof(s)) /* string clear */
-
- /*
- * Globals
- */
-
- char huge *fat, /* address of FAT */
- cdrive[66], /* startup drive and path */
- fat_16; /* true if 16 bit FAT entries */
-
- int sections = 0, /* file sections */
- secsize = 0 , /* sector size of drive */
- frag = 0, /* fragmented files */
- unfrag = 0, /* unfragmented files */
- files = 0, /* processed files */
- dirs = 0, /* processed directories */
- list = 0; /* list frag'd files switch */
-
- UINT nclusters; /* number of clusters */
-
- /*
- * formal declarations
- */
-
- void get_fat(int), /* read FAT into memory */
- cfexit(int), /* exit routine */
- check_frag(char *, UINT, int), /* check if file/dir is frag'd */
- dir_search(char *), /* search directory */
- strclr(char *, int, int), /* clear a string */
- check_unlinked(); /* check for unlinked clusters */
- int chkdrv(char); /* check local, SUBST/ASSIGN */
- char *fname(char *, char*), /* fcb filename to normal fname */
- *readlabel(char), /* read the drive label */
- *translate_name(char far *); /* translate name */
- UINT next_cluster(UINT, int, int *); /* find the next cluster in FAT */
-
- struct fcb
- {
- char hexff; /* extended fcb first byte */
- char extra[5]; /* extended fcb work area */
- char attrib; /* extended fcb attribute */
- char drive; /* fcb - drive */
- char filename[8]; /* fcb - filename */
- char ext[3]; /* fcb - extension */
- unsigned
- int block; /* fcb - block number */
- unsigned
- long filesize; /* fcb - file size */
- int date; /* fcb - file date */
- char system[10]; /* fcb - reserved area */
- char record; /* fcb - current record */
- unsigned
- long rnd_recno; /* fcb - random record number */
- } ;
-
- /************************************************************************
- * *
- * mainline *
- * *
- ************************************************************************/
-
- main(argc, argv)
- int argc; /* count of arguments */
- char *argv[]; /* argument strings */
- {
- int pf = 0, /* percent fragmented */
- ctc = 0, /* return code chosen */
- dc = 0, /* drive chosen */
- pe = 0, /* parm in error */
- rc, /* return code */
- i, j, /* loop counter, work */
- option = 0; /* program option */
- char *p; /* work pointer */
- static
- char drive[] = " :\\", /* drive and path to check */
- *rc_type[] =
- { "Percentage",
- "Number of Files",
- "Number of Extra Segments" },
-
- *suggestion[] =
- { "No fragmentation -- No action suggested",
- "Little fragmentation -- No action suggested",
- "Moderate fragmentation -- Defrag should be performed soon",
- "Fragmentation critical -- Defrag or Backup/Format/Restore" },
-
- *errors[] =
- { "Invalid drive specified",
- "Cannot CHKFRAG a network drive",
- "Cannot CHKFRAG a SUBST'd or ASSIGN'd drive",
- "Must run with DOS 2.0 or greater" },
-
- *options[] =
- { "/%", "/N", "/E", "/L" } ;
-
-
- printf("CHKFRAG 1.0 (c) Ziff Communications Co.\n%s%c%s\n",
- "PC Magazine ", 254, " Bob Flanders & Michael Holmes\n");
-
- getcwd(cdrive, sizeof(cdrive)); /* get current drive/path */
- *drive = *cdrive; /* ..setup default drive */
-
- for (i = 1; i < argc; i++) /* check each argument */
- {
- strupr(p = argv[i]); /* uppercase argument */
-
- if (strlen(p) == 2 && p[1] == ':') /* q. drive parm specified? */
- {
- *drive = *p; /* a. yes .. setup drive */
- dc++; /* .. show drive selected */
- }
-
- else
- {
- for (j = 0; strcmp(p, options[j]) /* search arguments */
- && (j < 4); j++);
-
- switch(j) /* based on argument */
- {
- case 0: /* /% option */
- case 1: /* /N option */
- case 2: /* /E option */
-
- option = j; /* set up the option value */
-
- ctc++; /* increment code type count*/
- break; /* exit switch */
-
- case 3: /* /L switch */
- list++; /* .. show listing wanted */
- break;
-
- case 4: /* error */
- pe = j; /* argument in error */
- break; /* .. error */
- }
- }
- }
-
- if (pe || (ctc > 1) || (list>1) || (dc > 1))/* q. any error? */
- { /* a. yes .. handle error */
- printf("\n\tformat\tCHKFRAG [d:] [/%% | /N | /E] [/L]\n\n");
- printf("\twhere\td: is the drive to check for fragmentation\n");
- printf("\t\t/%% sets errorlevel as a percentage\n");
- printf("\t\t/N sets errorlevel to number of fragmented files (max 254)\n");
- printf("\t\t/E sets errorlevel number of extra sections (max 254)\n");
- printf("\t\t/L causes fragmented files to be listed\n");
- cfexit(255);
- }
-
- if (i = chkdrv(*drive)) /* check drive, version err */
- {
- printf("Error: %s", errors[--i]); /* display any error */
- cfexit(255); /* tell the batch job */
- }
-
- get_fat(*drive - 'A'); /* read FAT into memory */
- dir_search(drive); /* search for files */
- check_unlinked(); /* check unlinked clusters */
-
- if (files + dirs) /* q. any files and dirs? */
- pf = (frag * 100) / (files + dirs); /* a. yes .. % files frag'd */
-
- if (!pf && frag) /* q. something frag'd */
- pf = 1; /* a. yes .. show non-zero */
-
- printf("\n%d Files, %d Directories,\n", /* report to user */
- files, dirs);
- printf("%d Unfragmented, %d Fragmented, %d Extra Sections\n",
- unfrag, frag, sections);
- printf("%d%% of files are fragmented\n\n", pf);
-
- switch(option) /* return w/errorlevel */
- {
- case 0: /* percentage return */
- rc = pf;
- break;
-
- case 1: /* files return */
- rc = frag > 254 ? 254 : frag;
- break;
-
- case 2: /* extra sections return */
- rc = sections > 254 ? 254 : sections;
- }
-
- if (pf == 0) /* q. no fragments? */
- i = 0; /* a. yes .. tell 'em */
-
- else if (pf < 11) /* q. little fragmentation? */
- i = 1; /* a. yes .. set index */
-
- else if (pf < 76) /* q. moderate fragm'tion */
- i = 2; /* a. yes .. setup msg */
-
- else
- i = 3; /* ..push the button, Jim */
-
- printf("%s%s\nCHKFRAG finished, Return code %d\n\n%s%s\n",
- "Return type chosen: ", rc_type[option], rc,
- "Suggestion:\n ", suggestion[i]);
-
- cfexit(rc); /* return w/errorlevel */
- }
-
- /************************************************************************
- * *
- * get_fat -- read boot record and fat into memory *
- * *
- ************************************************************************/
-
- void get_fat(drv)
- int drv; /* drive number */
- {
- union REGS r; /* work registers */
- struct SREGS s; /* ..and work segment regs */
- struct bootrec
- {
- char jmp[3], /* jump instruction */
- oem[8]; /* OEM name */
- UINT bytes; /* bytes per sector */
- char cluster; /* sectors per cluster */
- UINT res_sectors; /* reserved sectors */
- char fats; /* number of fats */
- UINT roots, /* number of root dir entries */
- sectors; /* total sectors */
- char media; /* media descriptor block */
- UINT fatsize, /* sectors per fat */
- tracksize, /* sectors per track */
- heads, /* number of heads */
- hidden; /* hidden sectors */
- } far *b_rec; /* boot record definition */
-
- char *nomem = "Not enough memory for processing\n";
-
- r.h.ah = 0x36; /* ah = get freespace */
- r.h.dl = drv + 1; /* get drive */
- int86(0x21, &r, &r); /* r.x.cx = bytes/sector */
-
- if ((BOOT = (struct bootrec far *) malloc(r.x.cx)) == NULL)
- { /* q. no memory? */
- printf(nomem); /* a. yes .. give */
- cfexit(255); /* ..error msg/exit */
- }
-
- r.h.al = drv; /* al = drive number */
- r.x.cx = 1; /* cx = number of sectors */
- r.x.dx = 0; /* dx = starting sector */
- r.x.bx = FP_OFF(BOOT); /* bx = offset of buffer */
- s.ds = FP_SEG(BOOT); /* ds = segment of buffer */
- int86x(0x25, &r, &r, &s); /* read boot sector */
-
- if (r.x.cflag) /* q. error reading disk? */
- {
- printf("Error reading boot record\n"); /* a. yes .. give error msg */
- cfexit(255); /* ..and return to DOS */
- }
-
- if ((fat = (char huge *) halloc((long) BOOT->fatsize * (long) BOOT->bytes, 1))
- == (char huge *) NULL)
- { /* q. no memory? */
- printf(nomem); /* a. yes .. give */
- cfexit(255); /* ..error msg/exit */
- }
-
- fat_16 = (BOOT->sectors / BOOT->cluster) > 4087;/* set if 16bit FAT tbl */
-
- r.h.al = drv; /* al = drive number */
- r.x.cx = BOOT->fatsize; /* cx = number of sectors */
- r.x.dx = BOOT->res_sectors; /* dx = starting sector */
- r.x.bx = FP_OFF(fat); /* bx = offset of buffer */
- s.ds = FP_SEG(fat); /* ds = segment of buffer */
- int86x(0x25, &r, &r, &s); /* read boot sector */
-
- if (r.x.cflag) /* q. error reading disk? */
- {
- printf("%02.2x %02.2x Error reading FAT\n",
- r.h.ah, r.x.di); /* a. yes .. give error msg */
- cfexit(255); /* ..and return to DOS */
- }
-
- nclusters = (BOOT->sectors - (BOOT->res_sectors
- + (BOOT->fatsize * BOOT->fats)
- + ((BOOT->roots * 32) / BOOT->bytes)))
- / BOOT->cluster;
-
- printf("Drive %c:%s %u Sectors, %u Clusters, %u Clustersize\n",
- drv + 'A', readlabel(drv + 'A'), BOOT->sectors, nclusters,
- BOOT->cluster * BOOT->bytes);
-
- printf("\nChecking disk structure ..");
-
- }
-
-
- /************************************************************************
- * *
- * check_frag -- check a file/directory for fragmentation *
- * *
- ************************************************************************/
-
- void check_frag(s, n, dflag)
- char *s; /* file/directory name */
- UINT n; /* starting cluster number */
- int dflag; /* directory flag */
- {
- UINT i, j; /* working storage */
- int flag = 0, /* flag for frag'd file */
- rc; /* error return code */
-
-
- for(; i = next_cluster(n, 1, &rc); n = i) /* walk down the chain */
- {
- if (i == 1) /* q. invalid cluster? */
- {
- printf("\n\t%s -- %s%s\n%s\n", /* a. yes .. give err msg */
- s, rc ? "Invalid cluster detected"
- : "File cross-linked",
- ", Run aborted",
- "\n\t** Please run CHKDSK **");
- cfexit(255); /* ..and exit w/error code */
- }
-
- if ((n + 1) != i) /* q. non-contiguous area? */
- {
- flag++; /* show fragmented file */
-
- if (i > n) /* q. possibly bad cluster? */
- {
- for (j = n + 1; /* check for bad spots */
- next_cluster(j, 0, &rc) == 0xfff7 && j < i;
- j++);
-
- if (j == i) /* q. was entire area bad? */
- flag--; /* a. yes .. don't report */
-
- else
- sections++; /* incr files sections count*/
- }
-
- else
- sections++; /* incr files sections count*/
- }
- }
-
- if (flag) /* q. fragmented file */
- {
- if (NOT frag && list) /* q. first frag file? */
- printf("\nFragmented Files/Directories:\n");
-
- if (list) /* q. list frag'd files? */
- printf("%s%s\n", /* a. yes .. give it to them*/
- dflag ? "DIR> " : " ", s);
-
- frag++; /* accumulate frag'd count */
- }
-
- else
- unfrag++; /* else total unfrag'd files*/
-
- }
-
-
- /************************************************************************
- * *
- * next_cluster -- return next cluster number from FAT *
- * *
- ************************************************************************/
-
- UINT next_cluster(n, x, rc)
- UINT n; /* current cluster number */
- int x, /* flag, 1 = reset FAT entry */
- *rc; /* error return code */
- {
- ULONG e; /* entry number in FAT */
- UINT huge *p, /* pointer for 16 bit FAT entry */
- mask1, mask2; /* mask for and'ing and or'ing */
- int flag; /* shift/and flag */
-
-
- *rc = 0; /* clear return code */
-
- if (! (e = n)) /* q. invalid cluster nbr */
- return(0); /* a. yes .. rtn EOF */
-
- if (fat_16) /* q. 16 bit FAT entries? */
- {
- p = (UINT *) &fat[0]; /* a. yes .. get FAT addr */
- n = p[e]; /* retrieve next entry */
-
- if (NOT n) /* q. unallocated cluster? */
- {
- n = 1; /* a. yes .. error condition*/
- *rc = 1; /* set return code */
- }
-
- if (x) /* q. need to reset entry? */
- p[e] = 1; /* a. yes .. show processed */
-
- if (n >= 0xfff0 && n != 0xfff7) /* q. reserved and not bad */
- n = 0; /* a. yes .. show EOF */
- }
-
- else
- {
- e = (n << 1) + n; /* cluster number * 3 */
- flag = e & 1; /* need to do shift later? */
- e >>= 1; /* cluster number * 1.5 */
- n = *(UINT *) &fat[e]; /* get next cluster */
-
- if (flag) /* q. need to do shift? */
- {
- n >>= 4; /* a. yes .. shift by 4 bits*/
- mask1 = 0x000f; /* mask to clear upper bits */
- mask2 = 0x0010; /* ..and footprint mask */
- }
-
- else
- {
- n &= 0xfff; /* else .. strip upper bits */
- mask1 = 0xf000; /* mask to clear lower bits */
- mask2 = 0x0001; /* ..and footprint mask */
- }
-
- if (NOT n) /* q. unallocated cluster? */
- {
- n = 1; /* a. yes .. error condition*/
- *rc = 1; /* set return code */
- }
-
- if (x) /* q. need to reset entry? */
- {
- *(UINT *) &fat[e] &= mask1; /* a. yes .. 'and' off bits */
- *(UINT *) &fat[e] |= mask2; /* ..and put down footprint */
- }
-
- if (n >= 0xff0) /* q. EOF/reserved range? */
- if (n == 0xff7) /* q. bad cluster? */
- n = 0xfff7; /* a. yes .. show bad one */
- else
- n = 0; /* else .. show EOF */
- }
-
- return(n);
-
- }
-
- /************************************************************************
- * *
- * check_unlinked -- check for unlinked clusters *
- * *
- ************************************************************************/
-
-
- void check_unlinked()
- {
- int rc; /* error return code */
- UINT i, /* loop counter */
- j; /* work return cluster nbr */
-
-
- for (i = 2; i < nclusters; i++) /* check thru entire FAT */
- {
- if ((j = next_cluster(i, 0, &rc)) != 0 /* q. unallocated cluster? */
- && j != 1 && j != 0xfff7) /* ..or used/bad cluster? */
- {
- printf("\nLost clusters detected, %s%s",/* a. no .. give msg */
- "Run aborted\n",
- "\t** Please run CHKDSK **\n");
- cfexit(255); /* ..and exit w/error */
- }
- }
- }
-
-
- /************************************************************************
- * *
- * dir_search -- recursively search all files & subdirectories *
- * *
- ************************************************************************/
-
- void dir_search(base_dir)
- char *base_dir; /* base subdirectory to search */
- {
- int oldds, /* old dta segment */
- oldda; /* old dta address */
- char pass, /* pass number */
- work_dir[65], /* work directory */
- first_done; /* find first done */
- struct fcb find_work; /* fcb work area */
-
- /*
- * The following areas are STATIC .. not allocated on recursion
- */
-
- static
- struct SREGS s; /* segment registers */
-
- static
- union REGS r; /* other registers */
-
- static
- char far *cftmp; /* work pointer */
-
- static
- int rc; /* work return code */
-
- static
- union
- {
- char dtabuff[128]; /* dta area */
-
- struct /* Disk transfer area layout */
- {
- char dta1[6]; /* first part of dta */
- char attrib; /* attribute byte */
- char drive; /* drive */
- char filename[8]; /* filename */
- char ext[3]; /* extension */
- char d_attrib; /* directory attribute */
- char dta2[10]; /* more reserved space */
- unsigned
- int d_time; /* directory time */
- unsigned
- int d_date; /* directory date */
- unsigned
- int d_cluster; /* first cluster */
- unsigned
- long d_filesize; /* size of file */
- } dta;
- } dta;
-
- /*
- * End of static area
- */
-
- r.h.ah = 0x2f; /* ah = get dta */
- int86x(0x21, &r, &r, &s); /* .. ask DOS */
-
- oldds = s.es; /* save old DTA segment */
- oldda = r.x.bx; /* .. and offset */
-
- cftmp = (char far *) &dta; /* get current fcb address */
-
- r.h.ah = 0x1a; /* ah = set DTA */
- s.ds = FP_SEG(cftmp); /* ds -> DTA segment */
- r.x.dx = FP_OFF(cftmp); /* ds:dx -> DTA */
- int86x(0x21, &r, &r, &s); /* setup new DTA */
-
- if (strcmp(base_dir, translate_name(base_dir))) /* q. JOIN'd? */
- return; /* a. yes .. skip it */
-
- chdir(base_dir); /* get the base directory */
-
- for(first_done=pass=0;;) /* look through current dir */
- {
- if (first_done == 0) /* q. find first done? */
- { /* a. no .. do it */
-
- if (base_dir[1] == ':') /* q. disk specified? */
- find_work.drive = /* a. yes .. set fcb drive */
- ((base_dir[0] & 0xdf) - 'A') + 1;
- else
- find_work.drive = 0; /* else use default */
-
- find_work.hexff = 0xff; /* extended fcb */
- CLEAR(find_work.extra, 0); /* set extra area */
- CLEAR(find_work.filename, '?'); /* .. and file name */
- CLEAR(find_work.ext, '?'); /* .. and extension */
- find_work.attrib = FILES; /* set up attribute to find */
-
- r.h.ah = 0x11; /* ah = find first */
- cftmp = (char far *) &find_work; /* get pointer to work fcb */
- s.ds = FP_SEG(cftmp); /* ds -> segment of fcb */
- r.x.dx = FP_OFF(cftmp); /* ds:dx -> offset */
- int86x(0x21, &r, &r, &s); /* .. find first */
-
- rc = r.h.al; /* get return code */
-
- first_done = 1; /* first find done */
- }
-
- else
- {
- r.h.ah = 0x12; /* ah = find next */
- cftmp = (char far *) &find_work; /* get pointer to work fcb */
- s.ds = FP_SEG(cftmp); /* ds -> segment of fcb */
- r.x.dx = FP_OFF(cftmp); /* ds:dx -> offset */
- int86x(0x21, &r, &r, &s); /* .. find first */
-
- rc = r.h.al; /* get return code */
- }
-
- strcpy(work_dir, base_dir); /* get current base */
-
- if (work_dir[strlen(work_dir)-1] != '\\') /* if needed .. */
- strcat(work_dir, "\\"); /* .. add a backslash */
-
- strcat(work_dir, /* .. add the name */
- fname(dta.dta.filename, dta.dta.ext));
-
- if (pass) /* q. second pass? */
- {
- if (rc) /* q. more files found? */
- break; /* a. no .. exit */
-
- if (!(dta.dta.d_attrib & _A_SUBDIR) /* q. directory? */
- || (dta.dta.filename[0] == '.')) /* .. or a dot dir? */
- continue; /* a. get next entry */
-
- dirs++; /* accumulate dir count */
- dir_search(work_dir); /* recursively call ourself */
- }
-
- else /* first pass processing */
- {
- if (rc) /* q. anything found? */
- { /* a. no .. */
- first_done = 0; /* re-execute find-first */
- pass++; /* go to next pass */
- continue; /* .. continue processing */
- }
-
- if (dta.dta.filename[0] == '.') /* q. dot directory? */
- continue; /* a. yes .. skip it */
-
- if (!(dta.dta.d_attrib & _A_SUBDIR)) /* q. a file? */
- files++; /* a. yes .. count them */
-
- check_frag(work_dir, /* check for frag'd file */
- dta.dta.d_cluster,
- dta.dta.d_attrib & _A_SUBDIR);
- }
- }
-
- r.h.ah = 0x1a; /* ah = set DTA */
- s.ds = oldds; /* ds -> DTA segment */
- r.x.dx = oldda; /* ds:dx -> DTA */
- int86x(0x21, &r, &r, &s); /* setup new DTA */
-
- }
-
-
- /************************************************************************
- * *
- * fname -- build a normalized filename from an FCB *
- * *
- ************************************************************************/
-
- char *fname(filename, ext)
- char *filename; /* filename with trailing blanks*/
- char *ext; /* extension */
- {
- int i; /* loop control */
- char *p; /* work pointer */
- static
- char fwork[13]; /* returned work area */
-
-
- p = fwork; /* initialize string pointer*/
-
- for (i = 0; (i < 8) && (*filename != ' '); i++) /* move fname w/o blanks*/
- *p++ = *filename++;
-
- if (*ext != ' ') /* q. extension blank? */
- {
- *p++ = '.'; /* a. no .. add the dot */
-
- for (i = 0; (i < 3) && (*ext != ' '); i++) /* add ext w/o blanks */
- *p++ = *ext++;
- }
-
- *p = 0; /* terminate string w/null */
-
- return(fwork); /* return string to caller */
-
- }
-
-
- /************************************************************************
- * *
- * strclr -- clear an area to a value *
- * *
- ************************************************************************/
-
- void strclr(s, c, n)
- char *s; /* area to initialize */
- int c, /* value to use */
- n; /* length of area to clear */
- {
-
- while(n--) /* initialize whole area */
- *s++ = c; /* ..to value specified */
-
- }
-
-
- /************************************************************************
- * *
- * translate_name -- translate a DOS name *
- * *
- ************************************************************************/
-
- char *translate_name(name)
- char far *name; /* name to translate */
- {
- static
- char translate_area[65], /* work/return area */
- far *sp; /* work pointer */
-
- union REGS r; /* work registers */
- struct SREGS s; /* ..and work segment regs */
-
-
- r.h.ah = 0x60; /* ah = translate */
-
- sp = (char far *) name; /* set up a pointer .. */
- r.x.si = FP_OFF(sp); /* set pointer to input name */
- s.ds = FP_SEG(sp); /* .. and segment */
-
- sp = (char far *) translate_area; /* set up a pointer .. */
- r.x.di = FP_OFF(sp); /* set pointer to output area */
- s.es = FP_SEG(sp); /* .. and segment */
- int86x(0x21, &r, &r, &s); /* translate the name */
-
- if (r.x.cflag) /* if bad name .. */
- return((char far *) NULL); /* .. return error */
-
- else
- return(translate_area); /* return xlated name */
- }
-
-
- /************************************************************************
- * *
- * chkdrv -- assure drive is LOCAL and not SUBST'd or ASSIGN'd *
- * *
- ************************************************************************/
-
- int chkdrv(c)
- char c; /* drive to check */
- {
- union REGS r; /* work registers */
- struct SREGS s; /* ..and work segment regs */
-
- static
- char wdrv[] = " :\\"; /* work area for drive name */
-
-
- if (_osmajor < 2) /* q. pre-DOS 2.00? */
- return(4); /* a. yes .. can't run it */
-
- if (_osmajor >= 3 && _osminor >= 1) /* q. DOS 3.1 or higher? */
- {
- r.x.ax = 0x4409; /* ah = ioctl, local test */
- r.h.bl = (c - 'A') + 1; /* bl = drive to test */
- int86(0x21, &r, &r); /* test drive */
-
- if (r.x.cflag) /* q. bad drive? */
- return(1); /* a. yes .. error */
-
- if (r.x.dx & 0x1000) /* q. remote? */
- return(2); /* a. yes .. error */
-
- wdrv[0] = c; /* set up name */
-
- if (strcmp(wdrv, translate_name(wdrv))) /* q. SUBST or ASSIGNED? */
- return(3); /* a. yes .. return error */
- }
-
- return(0); /* return ok */
-
- }
-
-
- /************************************************************************
- * *
- * Read drive label, if available *
- * *
- ************************************************************************/
-
- char *readlabel(c)
- char c; /* drive to check */
- {
- char *p, *q; /* work pointers */
- struct find_t f; /* structure for directory entry*/
-
- static
- char work_dir[13] = { " :\\*.*" } ; /* directory to check */
-
-
- work_dir[0] = c; /* setup for find first */
-
- if (_dos_findfirst(work_dir, LABEL, &f)) /* q. error on label get? */
- work_dir[0] = 0; /* a. yes .. then no label */
-
- else
- {
- for(p = work_dir, q = f.name; *q; q++) /* copy label w/o middle . */
- if (*q != '.') /* q. is this char a dot? */
- *p++ = *q; /* a. no .. copy it */
-
- *p = 0; /* terminate string */
- }
-
- return(work_dir); /* ..and return label string*/
-
- }
-
- /************************************************************************
- * *
- * cfexit() - return to DOS after resetting dir, dir *
- * *
- ************************************************************************/
-
- void cfexit(rc)
- int rc; /* return code to exit with */
-
- {
- int i; /* work variable */
-
- _dos_setdrive((*cdrive - 'A')+1, &i); /* reset the default drive */
- chdir(cdrive); /* .. and directory */
-
- exit(rc); /* .. and return to DOS */
- }
-
-